<template>
    <div ref="scroll" class="tbc-scroll" v-show="show">
        <div ref="container" :class="classList">
            <slot></slot>

            <div class="indicator loading" v-if="onLoading && !isLastPage && this.page > 1">
                <div><p class="c rotate"></p>
                    <p class="t">正在加载</p></div>
            </div>

            <div class="indicator loading" v-if="onLoading && isLastPage && this.page <= 1 && showNoData">
                <div><p class="t">没有数据</p></div>
            </div>

            <div class="indicator loading"
                 v-if="onLoading && isLastPage && this.page >= 1 && showNoMore && commontips">
                <div><p class="t">没有更多了</p></div>
            </div>

            <div :class="['indicator refresh loading']" :style="refreshStyle" v-if="refresh && refreshType"
                 style="height: 60px;">
                <div>
                    <p :class="['c', refreshRotate ? 'rotate':'']" :style="refreshProgress"></p>
                    <p class="t">{{refreshTip}}</p>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        props: {
            show: {
                type: Boolean,
                default: true
            },
            classList: {
                type: String,
                default: ''
            },
            refresh: {
                type: Function,
                default: null
            },
            onLoading: {
                type: Function,
                default: null
            },
            onScrollStart: {
                type: Function,
                default: null
            },
            onScroll: {
                type: Function,
                default: null
            },

            onScrollEnd: {
                type: Function,
                default: null
            },

            onTouchEnd: {
                type: Function,
                default: null
            },
            direction: {
                type: String,
                default() {
                    return 'vertical';
                }
            },
            refreshType: {
                type: Number,
                default: 1,
            },
            // 外层滚动
            outerScroll: {
                type: Object,
                default: null,
            },
            scrollHeight: {
                type: Number,
                default: 0
            },
            commontips: {  //清单没有更多提示
                type: Boolean,
                default: true
            },
            snap: {
                type: Boolean,
                default: false
            },
            goToPage: {
                type: Number,
                default: 0
            },
            bounce: {
                type: Boolean,
                default: true
            },
            //scroll冒泡
            stopPropagation: {
                type: Boolean,
                default: false
            },
            click: {
                type: Boolean,
                default: true
            },
            isCategory: {
                type: Boolean,
                default: true
            },
            scrollBoxHeight: {
                type: Number,
                default: 0
            }

        },

        data() {
            return {
                scroll: null,
                refreshStyle: '',
                callbackType: 0,  // 回调类型
                totalDataRow: 0,
                showLoading: false,
                refreshTip: '下拉刷新',
                isExcessOffset: false,
                refreshProgress: '',
                refreshRotate: false,
                isLastPage: false,
                page: 1,
                pageSize: 10,
                showNoData: false,
                showNoMore: true,
                totalRows: 0,    // 已加载数据条数
                callbackTimer: null,
            }
        },
        mounted() {
            setTimeout(() => {
                this.__initScroll();
            }, 100);
            // }, 20);

        },

        activated() {
            if (!this.scroll) return;
            this.scroll.refresh();
            this.scroll.stop();
        },

        deactivated() {
            this.scroll.stop();
        },
        watch: {
            show: function (val) {
                if (val) setTimeout(() => {
                    this.calcContainerMinHeight();
                }, 20)
            },
            scrollHeight: function (val) {
                this.scrollTo(0, -val)
            },
            goToPage: function (page) {
                this._goToPage(page)
            }
        },

        methods: {

            // 初始化滚动
            __initScroll() {
                if (!this.$refs.scroll) return;
                if (this.direction === 'vertical') this.calcContainerMinHeight();
                let options = {
                    click: true,
                    scrollX: this.direction === 'horizontal',
                    scrollY: this.direction === 'vertical',
                    snap: this.snap,  //轮播隔断
                    momentum: !this.snap,  //惯性
                    bounce: this.bounce,
                    stopPropagation: this.stopPropagation,
                    click: this.click,
                };

                // ios 触摸停止抖动
                if (window.navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) {
                    options.useTransition = false;
                }
                if (this.onScroll || this.direction === 'horizontal') options.probeType = 3;
                if (this.refresh) options.pullDownRefresh = {threshold: 60, stop: 60};
                if (this.onLoading) options.pullUpLoad = {threshold: 60};
                this.scroll = new BScroll(this.$refs.scroll, options);
                this.__onBeforeScrollStart();
                this.__onScrollStart();
                this.__onScroll();
                this.__onScrollEnd();
                this.__onTouchEnd();
                this.__listenRefresh();
                this.__listenLoading();
            },

            // 设置回调定时器
            __setCallbackTimer() {
                this.callbackTImer = setTimeout(() => {
                    this.finish(0);
                }, 10000);
            },

            // 获取样式表
            __getStyle(element, attr) {
                if (element.currentStyle) {
                    return element.currentStyle[attr];
                } else {
                    return window.getComputedStyle(element, null)[attr];
                }
            },

            // 计算容器最小高度
            calcContainerMinHeight() {
                if (this.$refs.container && (this.refresh || this.onLoading)) {
                    let height = this.$refs.scroll.offsetHeight
                    if (height != 0) {
                        this.$refs.container.style.minHeight = `${height + 1}px`
                    } else {
                        this.$refs.container.style.minHeight = `${this.scrollBoxHeight + 1}px`
                    }
                }
            },

            // 水平滚动计算长度
            calcWidth() {
                let width = 0;
                let children = this.$refs.container.children;
                width += parseFloat(this.__getStyle(children[0], 'width'));
                width += parseFloat(this.__getStyle(children[0], 'marginRight'));
                width += parseFloat(this.__getStyle(children[0], 'marginLeft'));
                width = width * children.length;
                this.$refs.container.style.width = `${width}px`
            },
            activityCalcWidth() {
                let width = 0;
                let lastWidth = 0
                let children = this.$refs.container.children;
                width += parseFloat(this.__getStyle(children[0], 'width'));
                width += parseFloat(this.__getStyle(children[0], 'marginRight'));
                width += parseFloat(this.__getStyle(children[0], 'marginLeft'));
                width += parseFloat(this.__getStyle(children[0], 'paddingLeft'));
                width += parseFloat(this.__getStyle(children[0], 'paddingRight'));
                lastWidth = width / 2
                width = width * (children.length - 1);
                width += lastWidth
                this.$refs.container.style.width = `${width}px`
            },

            // 滚动前回调
            __onBeforeScrollStart() {
                this.scroll && this.scroll.on("beforeScrollStart", () => {
                });
            },

            // 滚动开始回调
            __onScrollStart() {
                this.scroll && this.scroll.on("scrollStart", () => {
                    this.onScrollStart && this.onScrollStart();
                });
            },

            // 滚动中回调
            __onScroll() {
                this.scroll && this.scroll.on('scroll', (position) => {
                    if (this.outerScroll && this.scroll.movingDirectionX) {
                        this.outerScroll.scroll.disable();
                    }
                    if (this.refreshTip !== '正在刷新') {
                        this.refreshTip = (position.y > 60) ? '释放刷新' : '下拉刷新';
                    }
                    if (this.refresh) {
                        let rate = position.y / 60;
                        let rotate = rate * 360;
                        this.refreshProgress = `transform: rotate(${rotate}deg)`;
                    }
                    this.onScroll && this.onScroll(position, this.scroll);
                });
            },

            // 滚动结束回调
            __onScrollEnd() {
                this.scroll && this.scroll.on("scrollEnd", (position) => {
                    this.refreshRotate = false;
                    this.refreshTip = '下拉刷新';
                    this.onScrollEnd && this.onScrollEnd(position, this.scroll);
                });
            },

            // 手指离开回调
            __onTouchEnd() {
                this.scroll && this.scroll.on("touchEnd", (position) => {
                    if (this.outerScroll) this.outerScroll.scroll.enable();
                    this.onTouchEnd && this.onTouchEnd();
                });
            },

            // 监听刷新
            __listenRefresh() {
                this.refresh && this.scroll.on('pullingDown', () => {
                    this.scroll.disable();
                    this.showLoading = false;
                    this.refreshTip = '正在刷新';
                    this.refreshRotate = true;
                    this.isLastPage = false
                    this.page = 1;
                    this.totalRows = 0;
                    this.refresh(this);
                    this.__setCallbackTimer();
                });
            },

            // 监听加载
            __listenLoading() {
                this.onLoading && this.scroll.on("pullingUp", () => {
                    if (this.isLastPage) {
                        this.scroll.finishPullUp();
                        return this.scroll.enable();
                    }
                    this.showLoading = true;
                    this.page += 1;
                    this.onLoading(this);
                    this.__setCallbackTimer();
                });
            },

            //滚动到指定页面
            _goToPage(page) {
                this.scroll && this.scroll.goToPage(0, page, 300)
            },
            // 禁用滚动
            disable() {
                this.scroll && this.scroll.disable();
            },

            // 启用滚动
            enable() {
                this.scroll && this.scroll.enable();
            },

            //
            scrollTo(x, y, time = 500) {
                this.scroll && this.scroll.scrollTo(x, y, time);

            },

            // 停止滚动
            stop() {
                this.scroll && this.scroll.stop();
            },

            // 销毁插件
            destroy() {
                this.scroll && this.scroll.destroy();
            },

            // 触发刷新
            triggerRefresh() {
                setTimeout(() => {
                    this.scroll.refresh()
                    // this.scroll.disable();
                }, 20);
            },

            // 触发加载
            triggerLoading() {
                this.scroll && this.scroll.openPullDown();
            },
            // 回调结束
            finish(rows, pageSize) {
                if (!this.scroll) return
                if (!this.isCategory) this.isLastPage = false
                clearTimeout(this.callbackTImer);
                this.totalRows += rows;
                pageSize = pageSize || this.pageSize;
                if (rows < pageSize) this.isLastPage = true;
                if (this.page >= 2) this.scroll.finishPullUp();
                if (this.page <= 1) this.scroll.finishPullDown();
                if (!rows) return this.scroll.enable();
                setTimeout(() => {
                    this.scroll.refresh();
                    this.scroll.enable();
                }, 20);
            }
        }
    }
</script>
<style>
    .tbc-scroll .indicator {
        width: 100%;
        background: inherit;
        overflow: hidden;
        position: relative;
        font-size: 16px
    }

    .tbc-scroll .indicator > div {
        width: 100%;
        text-align: center;
    }

    .tbc-scroll .refresh {
        position: absolute;
        top: -60px;
        line-height: 0
    }

    .tbc-scroll .refresh img {
        max-width: 60px;
        max-height: 100%;
        display: inline-block;
    }

    .tbc-scroll .refresh > div {
        height: 100%;
        line-height: 0;
    }

    .tbc-scroll .refresh > div .i {
        height: 100%;
        line-height: 0;
    }

    .tbc-scroll .t {
        display: inline-block;
        font-size: .875em;
        color: #444;
        vertical-align: middle;
    }

    .tbs-scroll .refresh .t {
        padding-bottom: 10px;
    }

    .tbc-scroll .loading {
        height: 60px;
        line-height: 60px;
    }

    .tbc-scroll .indicator .c {
        display: inline-block;
        width: 1em;
        height: 1em;
        border-radius: 50%;
        border: 1px solid #444;
        margin-right: 8px;
        border-bottom-color: transparent;
        vertical-align: middle;
    }

    .tbc-scroll .c.rotate {
        -webkit-animation: rotate .6s linear infinite;
        animation: rotate .6s linear infinite;
    }

    @keyframes rotate {
        0% {
            transform: rotate(0deg)
        }
        100% {
            transform: rotate(360deg)
        }
    }

    @-webkit-keyframes rotate {
        0% {
            -webkit-transform: rotate(0deg)
        }
        100% {
            -webkit-transform: rotate(360deg)
        }
    }

    .tbc-scroll .animate {
        transition: top 300ms;
    }

    .tbc-scroll .refresh .light {
        line-height: 60px
    }

    .tbc-scroll .refresh .light .t {
        color: #FFF
    }

    .tbc-scroll .refresh .light .c {
        border: 1px solid #FFF;
        border-bottom-color: transparent;
    }
</style>